﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using XinLife.Core.Helper;

namespace XinLife.Common.Setup
{
    public static class AuthenticationSetup
    {
        /// <summary>
        /// 系统 授权服务 配置
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void AddAuthorizationSetup(this IServiceCollection services, IConfiguration configuration)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            var jwtConfig = configuration.GetSection("Jwt");
            var jwtOption = new JwtOption
            {
                Issuer = jwtConfig["Issuer"],
                Expiration = Convert.ToInt16(jwtConfig["Expiration"]),
                Secret = jwtConfig["Secret"],
                Audience = jwtConfig["Audience"]
            };
            //cookie jwt验证都会执行
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
             .AddCookie()
             .AddScheme<AuthenticationSchemeOptions, AuthentHandler>("UserAuthent", o => { })
             .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions =>
             {
                 //用于强制要求HTTPS连接
                 jwtBearerOptions.RequireHttpsMetadata = false;
                 jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateIssuerSigningKey = true,
                     IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(jwtOption.Secret)),//秘钥
                     ValidateIssuer = true,
                     ValidIssuer = jwtOption.Issuer,
                     ValidateAudience = true,
                     ValidAudience = jwtOption.Audience,
                     ValidateLifetime = true,
                     ClockSkew = TimeSpan.FromMinutes(5)
                 };
                 jwtBearerOptions.Events = new JwtBearerEvents
                 {
                     //用于自定义接收JWT令牌的方式，并在接收到令牌后执行额外的逻辑操作。
                     OnMessageReceived = context =>
                     {
                         var accessToken = context.Request.Query["access_token"];
                         var path = context.HttpContext.Request.Path;
                         if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/hub")))
                         {
                             context.Token = accessToken;
                         }
                         return Task.CompletedTask;
                     },
                     //用于在JWT令牌验证成功后执行额外的逻辑操作，例如从令牌中提取用户信息并创建用户身份。
                     OnTokenValidated = context =>
                     {
                         return Task.CompletedTask;
                     },
                     //用于在JWT令牌验证失败时执行额外的逻辑操作，例如记录日志或返回自定义错误消息。
                     OnAuthenticationFailed = context =>
                     {
                         // 如果过期，则把<是否过期>添加到，返回头信息中
                         if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                         {
                             context.Response.Headers.Add("Token-Expired", "true");
                         }
                         context.Fail("Unauthorized");
                         return Task.CompletedTask;
                     },
                     //验证失败后触发
                     OnChallenge = context =>
                     {
                         return Task.CompletedTask;
                     },
                 };
             });
            services.AddSingleton(jwtOption);//注册配置
        }

    }
}
